home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / ARGONET / PD / GRAPHICS / GIF2RPC.SPK / source / s / map16_accura next >
Text File  |  1995-10-02  |  7KB  |  206 lines

  1. ; map16_accurate.s
  2. ; MACHINE:     RISC OS
  3. ; LANGUAGE:    OBJASM assembler
  4. ; AUTHOR:      Cy Booker, cy@cheepnis.demon.co.uk
  5. ; LICENSE:     FreeWare, Copyright (c) Cy Booker 1995
  6. ; PURPOSE:     Given an arbitary 48-bit colour, what is the closest 16-bit colour?
  7.  
  8.         GET     OS:Hdr.os
  9.  
  10. ;
  11. ; in middle we have |intensity-difference| <-- 0xffff * 2 / 0x1f
  12. ; so |i|^2 < 0x0110c631
  13. ; and so |d|^2 < 0x03325293
  14. ;
  15. ; the weights we want are:
  16. ;       Red     * 0.212671      *256 =  54 (0x36)  *179 =  38 0x26
  17. ;       Green   * 0.715160      *256 = 183 (0xb7)  *179 = 128 0x80
  18. ;       Blue    * 0.072169      *256 =  19 (0x13)  *179 =  13 0x0d
  19. ;
  20. ; note we will use the *179 because it makes the inline multiplies very quick
  21. ; note we divide by 4 so that total difference fits in 32 (unsigned) bits
  22. ; ie (0x03325293 * 179 / 4) < 2^32
  23. ;
  24.  
  25.         MACRO 
  26.         Dump
  27.  [ {FALSE}
  28.          STMFD sp!, {a1-v6, ip, lr}
  29.          STMFD sp!, {d}
  30.          MOV a4, delta_grn
  31.          MOV a3, delta_blu
  32.          MOV a2, delta_red
  33.          ADR a1, __format
  34.          IMPORT _printf
  35.         ; BL _printf
  36.          B %FT1
  37. _format = "delta= {%8x, %8x, %8x}, dist= %8x\n", 0
  38.         ALIGN
  39. 1
  40.         ADD sp, sp, #4
  41.         LDMFD sp!, {a1-v6, ip, lr}
  42.  ]
  43.         MEND
  44.  
  45.  
  46.         EXPORT  map_scaled_rgb_to_16bpp_colour_accurate
  47.  
  48.         AREA |ARM$$code|, CODE, READONLY
  49.  
  50.         ROUT
  51.  
  52. ;
  53. ; In    R0 -> structure, or NULL
  54. ;       R1 = red nominally [0, 0xffff], but clipped as necessary
  55. ;       R2 = green nominally [0, 0xffff], but clipped as necessary
  56. ;       R3 = blue nominally [0, 0xffff], but clipped as necessary
  57. ; Out   R0 = 16 bit colour number (%0bbb bbgg gggr rrrr)
  58. ;       structure[0] = error in approximating red intensity
  59. ;       structure[1] = error in approximating green intensity
  60. ;       structure[2] = error in approximating blue intensity
  61. ;
  62.  
  63.         ROUT
  64.  
  65. str             RN      a1
  66. orig_red        RN      a2
  67. orig_grn        RN      a3
  68. orig_blu        RN      a4              ; implicit
  69. delta_red       RN      v1              ;\;
  70. delta_grn       RN      v2              ; \;
  71. delta_blu       RN      v3              ;-->
  72. scaled_red      RN      v4              ;\;
  73. scaled_grn      RN      v5              ; \;
  74. scaled_blu      RN      v6              ;-->
  75. t               RN      ip
  76. delta           RN      str
  77. d               RN      scaled_red
  78. dmin            RN      scaled_blu
  79.  
  80.  
  81.         ^ 0, sp
  82. L_str           # 4                             ; all structure offsets are implicit!
  83. L_best_delta    # 4 * 3
  84. L_scaled_red    # 4
  85. L_scaled_grn    # 0                             ; this is in a register!
  86. L_scaled_blu    # 4
  87. L_distance_red  # 4                             ; need to remember this
  88. sizeof_L        * :INDEX: {VAR}
  89.  
  90.  
  91. map_scaled_rgb_to_16bpp_colour_accurate
  92.  
  93.  
  94.         STMFD   sp!, {v1-v6, lr}
  95.         STR     str, [sp, #-sizeof_L]!                  ; store and reserve stack space
  96.         MOV     lr, #0xff00
  97.         ORR     lr, lr, #0xff
  98.         CMP     orig_red, #0x10000                      ; ensure in range [0, 0xffff]
  99.         MOVHS   orig_red, #0
  100.         MOVGE   orig_red, lr
  101.         CMP     orig_grn, #0x10000
  102.         MOVHS   orig_grn, #0
  103.         MOVGE   orig_grn, lr
  104.         CMP     orig_blu, #0x10000
  105.         MOVHS   orig_blu, #0
  106.         MOVGE   orig_blu, lr
  107.  
  108.         AND     t, orig_red, #&f800             ; t = simple approximation of red * 2 ^ (16 - 5)
  109.         ORR     t, t, t, LSR #5
  110.         ORR     t, t, t, LSR #10
  111.         ORR     t, t, t, LSR #15                ; t ~= t * 0xffff / 0x1f
  112.         STR     t, L_scaled_red
  113.  
  114.         AND     t, orig_grn, #&f800
  115.         ORR     t, t, t, LSR #5
  116.         ORR     t, t, t, LSR #10
  117.         ORR     scaled_grn, t, t, LSR #15
  118.  
  119.         AND     t, orig_blu, #&f800
  120.         ORR     t, t, t, LSR #5
  121.         ORR     t, t, t, LSR #10
  122.         ORR     t, t, t, LSR #15
  123.         STR     t, L_scaled_blu
  124.  
  125.         MOV     delta, #&0800
  126.         ORR     delta, delta, #&0042                   ; delta= 0xffff / 0x1f
  127.         MOV     dmin, #&ffffffff
  128.  
  129.         MOV     delta_red, delta
  130. red_loop
  131.         LDR     t, L_scaled_red
  132.         ADD     t, t, delta_red
  133.         CMP     t, #0x10000
  134.         BHS     skip_red_loop                           ; ensure in range [0, 0xffff]
  135.         SUBS    d, t, orig_red
  136.         RSBMI   d, d, #0                                ; makes multiply faster
  137.         MULNE   t, d, d
  138.         ; scale for red...
  139.         ADDNE   d, t, t, LSR #1                         ; |r|^2 * 0.072169 * 179 / 4 = |r|^2 * 0x06
  140.         ADDNE   d, d, t, LSL #3                         ; |r|^2 * 0.072169 * 179 / 4 = |r|^2 * 0x26
  141.         STR     d, L_distance_red
  142.  
  143.         MOV     delta_blu, delta
  144. blu_loop
  145.         LDR     t, L_scaled_blu
  146.         ADD     t, t, delta_blu
  147.         CMP     t, #0x10000
  148.         BHS     skip_blu_loop                           ; ensure in range [0, 0xffff]
  149.  
  150.         SUBS    t, t, orig_blu
  151.         RSBMI   t, t, #0
  152.         MULNE   lr, t, t 
  153.         ; scale for blue
  154.         ADDNE   d, d, lr                                ; (|b|^2 / 4) * 0x04
  155.         ADDNE   d, d, lr, LSR #2                        ; (|b|^2 / 4) * 0x05
  156.         ADDNE   d, d, lr, LSL #1                        ; (|b|^2 / 4) * 0x0d
  157.  
  158.         MOV     delta_grn, delta
  159. grn_loop
  160.         ADD     t, scaled_grn, delta_grn
  161.         CMP     t, #0x10000
  162.         BHS     skip_grn_loop                           ; ensure in range [0, 0xffff]
  163.         SUBS    t, t, orig_grn
  164.         RSBMI   t, t, #0                                ; speeds up multiplication
  165.         MUL     lr, t, t
  166.         ; scale for green ...
  167.         ADD     d, d, lr, LSL #5                        ; |g|^2 * 0.715160 * 179 / 4 = |g|^2 * 0x80
  168.         Dump
  169.         CMP     d, dmin
  170.         MOVLO   dmin, d
  171.         STMLOIB sp, {delta_red, delta_grn, delta_blu}   ; note the best so far
  172.         SUB     d, d, lr, LSL #5                        ; restore distance accumulator
  173. skip_grn_loop
  174.         SUBS    delta_grn, delta_grn, delta
  175.         BLS     grn_loop                                ; loop +1, 0, -1
  176.  
  177.         LDR     d, L_distance_red                       ; restore distance accumulator
  178. skip_blu_loop
  179.         SUBS    delta_blu, delta_blu, delta
  180.         BLS     blu_loop                                ; loop +1, 0, -1
  181.  
  182. skip_red_loop
  183.         SUBS    delta_red, delta_red, delta
  184.         BLS     red_loop                                ; loop +1, 0, -1
  185.  
  186.         ; the final lr is just to clear the stack
  187.         LDMIA   sp!, {str, delta_red, delta_grn, delta_blu, scaled_red, scaled_blu, lr}
  188.         ADD     scaled_red, scaled_red, delta_red
  189.         ADD     scaled_grn, scaled_grn, delta_grn
  190.         ADD     scaled_blu, scaled_blu, delta_blu
  191.         TEQ     str, #0
  192.         SUBNE   orig_red, orig_red, scaled_red
  193.         SUBNE   orig_grn, orig_grn, scaled_grn
  194.         SUBNE   orig_blu, orig_blu, scaled_blu
  195.         STMNEIA str, {orig_red, orig_grn, orig_blu}     ; store `error'
  196.  
  197.         MOV     t, scaled_red, LSR #16 - 5
  198.         MOV     lr, scaled_grn, LSR #16 - 5
  199.         ORR     t, t, lr, LSL #5
  200.         MOV     lr, scaled_blu, LSR #16 - 5
  201.         ORR     a1, t, lr, LSL #10                      ; construct 16-bit colour number
  202.  
  203.         LDMFD   sp!, {v1-v6, pc}^
  204.  
  205.   END
  206.